package com.lvmama.rhino.utils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis访问工具类，单例实现，仅适用于Redis集群部署
 * @author wxliyong
 */
public class JedisClusterUtils {
	private static Object LOCK = new Object();
	/** 存储Map的所有key值的后缀 */
	private static JedisClusterUtils instance;
	private JedisCluster jedisCluster;
	private static Properties properties = getProperties("redis.properties");
	private JedisClusterUtils(JedisCluster jedisCluster) {
		this.jedisCluster = jedisCluster;
	}
	
	public long del(String keys) {
		Long result = jedisCluster.del(keys);
		if(result == null) {
			return 0L;
		}
		return result;
	}
	
	public String set(String key, String value) {
		String result = jedisCluster.set(key, value);
		return result;
	}
	
	/**
	 * 将Map对象存入Redis，若是空Map将不做任何处理
	 * @param hash 所有value值必须是可序列化的
	 */
	public String hmset(String key, Map<String, Object> hash) {
		Map<String, String> jedisMap = new HashMap<String, String>();
		Set<String> keySet = hash.keySet();
		if(keySet.size() != 0) {
			Iterator<String> it = keySet.iterator();
			String[] keys = new String[keySet.size()]; 
			int index = 0;
			while(it.hasNext()) {
				String hashKey = it.next();
				keys[index++] = hashKey;
				try {
					jedisMap.put(hashKey, SerializeUtils.serialize(hash.get(hashKey)));
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else {
			// 若是入参中的Map为空，则默认是为了将Map清空，那么就直接删除该KEY
			jedisCluster.del(key);
			return "OK";
		}
		return jedisCluster.hmset(key, jedisMap);
	}
	
	/**
	 * 将Map对象存入Redis，若是空Map将不做任何处理
	 * @param hash 所有value值必须是可序列化的
	 */
	public String hmset(String key, Map<String, Object> hash, int seconds) {
		String result = hmset(key, hash);
		if("OK".equals(result)) {
			jedisCluster.expire(key, seconds);
		}
		return result;
	}
	
	public void hmdel(String key) {
		jedisCluster.del(key);
	}
	
	public Map<String, Object> hmget(String key) {
		Map<String, Object> result = new HashMap<String, Object>();
		Map<String, String> redisResult = jedisCluster.hgetAll(key);
		Iterator<String> it = redisResult.keySet().iterator();
		while(it.hasNext()) {
			String mapKey = it.next();
			String value = redisResult.get(mapKey);
			Object valueObj = null;
			if(value != null) {
				valueObj = SerializeUtils.deserialize(value);
			}
			result.put(mapKey, valueObj);
		}
		return result;
	}
	
	/**
	 * 存储一对key-value，并设置过期时间
	 * @param key
	 * @param value
	 * @param seconds 有效秒数
	 * @return Redis存储结果，OK-存储成功
	 */
	public String set(String key, String value, int seconds) {
		return jedisCluster.setex(key, seconds, value);
	}
	
	public String get(String key){
		return jedisCluster.get(key);
	}
	
	/**
	 * 递增计数器
	 * @param key
	 * @return 递增后的结果值
	 */
	public long incr(String key) {
		return jedisCluster.incr(key);
	}
	
	/**
	 * 递减计数器
	 * @param key
	 * @return 递减后的结果值
	 */
	public long decr(String key) {
		return jedisCluster.decr(key);
	}
	
	public void lpush(String key, String... values) {
		jedisCluster.lpush(key, values);
	}
	
	public List<String> lget(String key) {
		return lget(key, 0);
	}
	
	public List<String> lget(String key, long start) {
		Long length = jedisCluster.llen(key);
		if(length == null || length <= 0 || start > length) {
			return new ArrayList<String>();
		}
		return jedisCluster.lrange(key, start, length);
	}
	
	public static JedisClusterUtils getInstance() {
		if (instance==null) {
			synchronized(LOCK) {
				if (instance==null) {
					int maxIdle = Integer.parseInt(properties.getProperty("redis.maxIdle"));
					int minIdle = Integer.parseInt(properties.getProperty("redis.minIdle"));
					int maxTotal = Integer.parseInt(properties.getProperty("redis.maxTotal"));
					int maxWaitMillis = Integer.parseInt(properties.getProperty("redis.maxWaitMillis"));
					JedisPoolConfig config = new JedisPoolConfig();
					config.setMaxTotal(maxTotal);
					config.setMaxIdle(maxIdle);
					config.setMinIdle(minIdle);
					config.setMaxWaitMillis(maxWaitMillis);
					
					String serversStr = properties.getProperty("redis.servers").trim();
					String[] servers = serversStr.split(",");
					Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
					for(String server : servers) {
						String[] hostOrPort = server.split(":");
						jedisClusterNodes.add(new HostAndPort(hostOrPort[0], Integer.parseInt(hostOrPort[1])));
					}
					instance = new JedisClusterUtils(new JedisCluster(jedisClusterNodes, 2000, 2, config));
				}
			}
		}
		return instance;
	}
	
	/**
	 * 根据路径返回配置文件
	 * @param path
	 * @return
	 */
	private static final Properties getProperties(String path) {
		Properties properties = new Properties();
		try {
			InputStream inputStream = JedisClusterUtils.class.getClassLoader().getResourceAsStream(path);
			properties.load(inputStream);
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
			e.printStackTrace();
		}
		return properties;
	}
}
